require 'httpclient'
require 'rexml/document'

class Subtenant
  
  attr_accessor :name, :id, :authenticationSource, :status, :adminList
  def initialize (n, i, as, s, al) 
    @name = n
    @id = i
    @authenticationSource = as
    @status = s
    @adminList = al
  end

end

class PolicySelector

  attr_accessor :edit_mode, :id, :specname, :user_field_name, :user_operator, :user_value, :user_event, :sys_field_name, :sys_operator, :sys_value, :sys_event, :xquery, :adv_event, :operation_type
  
#"perform_action=create&entry_index=&entry[edit_mode]=0&entry[spec_name]=&entry[event]=&entry[id]=default&other[specname]=def&entry[user_field_name]=filename&entry[user_operator]=EQUALS&entry[user_value]=xxx&entry[user_event]=ON_CREATE&entry[sys_field_name]=atime&entry[sys_operator]=EQUALS&entry[sys_value]=&entry[sys_event]=ON_CREATE&entry[xquery]=&entry[adv_event]=ON_CREATE&operation_type=sync"

  def initialize(mode, id, specname, fname, operator, value, event, sname, sop, sval, sev, xquery, adv,optype)
    @edit_mode=mode
    @id=id
    @specname=specname
    @user_field_name=fname
    @user_operator=operator
    @user_value=value
    @user_event=event
    @sys_field_name=sname
    @sys_operator=sop
    @sys_value=sval
    @sys_event=sev
    @xquery=xquery
    @adv_event=adv
    @operation_type = optype
  end
  
  #validate that all the selections within a policy selector line up with existing business rules - 
  # left as an exercise
  def validate()
    
  end
  
  def to_s()
    "perform_action=create&entry_index=&entry[edit_mode]=" + @edit_mode + "&entry[spec_name]=&entry[event]=&entry[id]=" + @id + "&other[specname]=" + @specname + 
      "&entry[user_field_name]=" + fname + "&entry[user_operator]=" + operator + "&entry[user_value]=" + value + "&entry[user_event]=" + event + "&entry[sys_field_name]=" + sname + "&entry[sys_operator]=" + sop + "&entry[sys_value]=" + sval + "&entry[sys_event]=" + sev + "&entry[xquery]=" + xquery + "&entry[adv_event]=" + adv + "&operation_type=" +optype
  end

end

def PolicySpec
  attr_accessor :action, :specname
  
#  def initialize (perform_action=create&other[specname]=def&entry[spec_name]=&new_spec=true&replica_id=&metadata[1][location_modifier]=sameAs&metadata[1][location_place]=ANY&spec[1][type]=sync&spec[1][location_modifier]=sameAs&spec[1][location_place]=ANY&spec[1][ssattrs_placement]=OPTIMAL&spec[1][ssattrs_actions]=ANY&spec[1][stripe_number]=&spec[1][stripe_size]=&spec[1][stripe_units]=B&spec[1][service_name]=&spec[1][alg]=CRS&spec[1][fragmentation]=fragmentation1&other[read_access]=geographic&other[retention_year]=&other[retention_month]=&other[retention_day]=&other[retention_hour]=&other[retention_minute]=&other[retention_second]=&other[deletion_year]=&other[deletion_month]=&other[deletion_day]=&other[deletion_hour]=&other[deletion_minute]=&other[deletion_second]=&operation_type=sync)  end
  
  def to_s
   # val = "perform_action=%s&other[specname]=%s&entry[spec_name]%s="

    #perform_action=create&other[specname]=def&entry[spec_name]=&new_spec=true&replica_id=&metadata[1][location_modifier]=sameAs&metadata[1][location_place]=ANY&spec[1][type]=sync&spec[1][location_modifier]=sameAs&spec[1][location_place]=ANY&spec[1][ssattrs_placement]=OPTIMAL&spec[1][ssattrs_actions]=ANY&spec[1][stripe_number]=&spec[1][stripe_size]=&spec[1][stripe_units]=B&spec[1][service_name]=&spec[1][alg]=CRS&spec[1][fragmentation]=fragmentation1&other[read_access]=geographic&other[retention_year]=&other[retention_month]=&other[retention_day]=&other[retention_hour]=&other[retention_minute]=&other[retention_second]=&other[deletion_year]=&other[deletion_month]=&other[deletion_day]=&other[deletion_hour]=&other[deletion_minute]=&other[deletion_second]=&operation_type=sync

  end

end

# - diff between tenant and security admin?


class Basemgmt

  attr_accessor :client

  def initialize
    
  end

  def https_call(uri, headers, method="GET", body="")
    query=""
    case method
    when "GET"
      v =@client.get_content(uri, query, headers)
    when "POST"
      v=@client.post(uri, body, headers)
    when "HEAD"
      v=@client.head(uri, query=nil, headers)
    when "DELETE"
      v=@client.delete(uri, headers)
    end

    return v
  end
end

class MGMT < Basemgmt
  attr_accessor :username, :password, :accesspoint
  
  def initialize (username, password, accesspoint, cert_path='/usr/local/lib/site_ruby/1.8/httpclient/cacert.p7s')
    @accesspoint = accesspoint
    @username = username
    @password = password
    @cert = cert_path
    @client = HTTPClient.new
    @client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
    @client.ssl_config.set_trust_ca(@cert)
  end

  def getNodeInfo(rmgName, nodeName)
    uri = @accesspoint+"/sysmgmt/rmgs/" + rmgName + "/nodes/" + nodeName
    headers=[['x-atmos-systemadminpassword', @password], ['x-atmos-systemadmin', @username], ['x-atmos-authtype', 'password']]  
    https_call(uri, headers)
  end

  def getNodesList(rmgName)
    uri = @accesspoint+"/sysmgmt/rmgs/" + rmgName + "/nodes/"
    headers=[['x-atmos-systemadminpassword', @password], ['x-atmos-systemadmin', @username], ['x-atmos-authtype', 'password']]  
    https_call(uri, headers)
  end

  def getRMGInfo(rmgName)
    uri = @accesspoint+"/sysmgmt/rmgs/" + rmgName
    headers=[['x-atmos-systemadminpassword', @password], ['x-atmos-systemadmin', @username], ['x-atmos-authtype', 'password']]  
    https_call(uri, headers)
  end

  def getRMGList
    uri = @accesspoint+"/sysmgmt/rmgs/"
    headers=[['x-atmos-systemadminpassword', @password], ['x-atmos-systemadmin', @username], ['x-atmos-authtype', 'password']]  
    https_call(uri, headers)
  end


end

#todo 
#better cert management
#

class SubtenantMgmt < Basemgmt

  attr_accessor :tenant, :tenantadmin, :password, :accesspoint, :authsource
  
  def initialize (tenant, tenantadmin, password, accesspoint, authsource="local",cert_path='/Library/Ruby/Site/1.8/httpclient/cacert.p7s')

    @accesspoint = accesspoint
    @password = password
    @tenant = tenant
    @tenantadmin = tenantadmin
    @authsource = authsource
    @client = HTTPClient.new
    @client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
    @client.ssl_config.set_trust_ca(cert_path)
    @headers=[['x-atmos-tenantadmin', @tenantadmin], ["x-atmos-tenantadminpassword", @password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", @authsource]]

  end

# Subtenant Management
  def createSubtenant (subtenant)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants"
    @headers.push(["x-atmos-subtenantname", subtenant])
    xmlrval = https_call(uri, @headers,"POST")
    return xmlrval
  end

# Subtenant Management
  def deleteSubtenant (subtenant)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant
    xmlrval = https_call(uri, @headers,"DELETE")  
    print xmlrval.content
  end

# Subtenant Management
#return array of names of subtenants
  def listSubtenants
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants"
    xmlrval = https_call(uri, @headers,"GET")
    doc = REXML::Document.new(xmlrval)
    subs = Array.new
    doc.elements.each('subtenantList/subtenant/name') { |element|
      subs << element.text
    }
    return subs
  end

  def readSubtenants(subtenant)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant
    xmlrval=https_call(uri, @headers,"GET")
    doc = REXML::Document.new(xmlrval)
    return doc
  end


  def renameSubtenant(oldsubtenant, newsubtenant)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + oldsubtenant
    @headers.push(["x-atmos-subtenantname", newsubtenant])
    @headers.push(["x-atmos-action", "rename"])
    xmlrval=https_call(uri, @headers,"PUT")    
    doc = REXML::Document.new(xmlrval)
    return doc
  end
## Managing UID'
  def createUID(subtenant, uid)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant + "/uids"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'],["x-atmos-uid",uid]]
    https_call(uri, headers,"POST")    
  end

  def deleteUID(tenant, subtenant, uid)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant + "/uids/" + uid
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"DELETE")    
  end

  #action mnust be one of disable, enable, reset
  def manageSubtenant(tenant, tenantadmin,subtenant,password, uid, action)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant +"/uids/" + uid
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"], ["x-atmos-action", action]]
    https_call(uri, headers,"PUT")    
  end
  
  def listUIDS(tenant, tenantadmin,subtenant,password)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant +"/uids" 
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"GET")    
  end


  def readSharedSecret(tenant, tenantadmin,subtenant,password, uid)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant +"/uids/" + uid 
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"GET")    
  end

  def readSharedSecret(tenant, tenantadmin,subtenant,password, uid)
    uri = @accesspoint+"/sysmgmt/tenants/"+tenant+ "/subtenants/" + subtenant +"/uids/" + uid 
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"GET")    
  end

  
  def assignPolicySelector(tenant, tenantadmin, password, selector, subtenants)
    uri = @accesspoint+"/sysmgmt/"+tenant+ "/policyselectors/assign"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    data = "selectors="+selector+"&policy_type=0&subtenants[]="+subtenants
    https_call(uri, headers,"POST", data)    
  end

  def createPolicySelector(tenant, tenantadmin, password, selector,policydef)
    uri = @accesspoint+"/sysmgmt/"+tenant+ "/policyselectors"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"POST", policydef.to_s)    
  end

  def deletePolicySelector(tenant, tenantadmin, password, selector,policyname)
    uri = @accesspoint+"/sysmgmt/"+tenant+ "/policyselectors/"+policyname
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"DELETE")    
  end

  def getPolicySelector(tenant, tenantadmin, password, selector, policyname)
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policyselectors/" + policyname
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"GET")  
  end

  def listPolicySelector
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policyselectors"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"GET")  
  end

  def updatePolicySelector(tenant, tenantadmin, password, selector, policydef)
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policyselectors/" + selector
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password'], ["x-atmos-authsource", "local"]]
    https_call(uri, headers,"POST", policydef.to_s)  
  end
  
  #
  # Managing policy specifications
  #
  
  
  def createPolicy(tenant, tenantadmin, password, policydef)
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policies"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"POST", policydef.to_s)  
  end

  def deletePolicy(tenant, tenantadmin, password,policyname)
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policies/" + policyname
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"DELETE")  
  end

  def listPolicy
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policies"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"GET")  
  end

  def readPolicy(policyname)
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policies/" + policyname
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"GET")  
  end

  def updatePolicy(policyname, policydef)
    uri = @accesspoint + "/sysmgmt/" + tenant + "/policies/" + policyname
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"PUT", policydef.to_s)  
  end
  
  #
  # Monitoriging
  #
  
  def getWebStats(rmg, nodename)
    uri = @accesspoint + "/sysmgmt/rmgs/" + rmg + "/nodes/" + nodename/wsstats
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"GET")  
    
  end
  
  def getTenantStorageMetrics
    uri = @accesspoint + "/sysmgmt/tenants/" + tenant+ "/scMetrics"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"GET")  

  end

  def getSubtenantStorageMetrics
    uri = @accesspoint + "/sysmgmt/tenants/" + tenant+ "/"+subtenant+ "/scMetrics"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"GET")  

  end

  def getUIDStorageMetrics(tenant, tenandadmin, subtenant, uid,password)
    uri = @accesspoint + "/sysmgmt/tenants/" + tenant+ "/"+subtenant+ "/"+uid+"/scMetrics"
    headers=[['x-atmos-tenantadmin', tenantadmin], ["x-atmos-tenantadminpassword", password],['x-atmos-authtype', 'password']]
    https_call(uri, headers,"GET")  

  end


end
